﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.NetworkInformation;

namespace Innovox.NetTools
{
    public class PingRange
    {

        public IPAddress StartRange {get;set;}
        public IPAddress EndRange {get;set;}
        public bool Valid
        {
            get
            {
                byte[] startBytes = StartRange.GetAddressBytes();
                byte[] endBytes = EndRange.GetAddressBytes();
                return (StartRange.Address != 0 && EndRange.Address != 0)
                    && (startBytes[0] <= endBytes[0])
                    && (startBytes[1] <= endBytes[1])
                    && (startBytes[2] <= endBytes[2])
                    && (startBytes[3] <= endBytes[3])
                    && (startBytes[0] < 255 && endBytes[0] < 255)
                    && (startBytes[1] < 255 && endBytes[1] < 255)
                    && (startBytes[2] < 255 && endBytes[2] < 255)
                    && (startBytes[3] < 255 && endBytes[3] < 255)
                    && (endBytes[3] > 0);
            }
        }

        public PingRange(IPAddress startRange, IPAddress endRange)
        {
            StartRange = startRange;
            EndRange = endRange;
        }

        public PingRange(string startRange, string endRange)
        {
            StartRange = IPAddress.Parse(startRange);
            EndRange = IPAddress.Parse(endRange);
        }

        public PingRange(long startRange, long endRange)
        {
            StartRange = new IPAddress(startRange);
            EndRange = new IPAddress(endRange);
        }

        static public PingRange GetNetworkIpRange()
        {
            IPAddress mask = new IPAddress(0);
            IPAddress gateway = new IPAddress(0);

            foreach (NetworkInterface networkCard in NetworkInterface.GetAllNetworkInterfaces())
            {
                //if (networkCard.NetworkInterfaceType == NetworkInterfaceType.Ethernet && networkCard.OperationalStatus == OperationalStatus.Up)
                if (networkCard.OperationalStatus == OperationalStatus.Up)
                {
                    mask.Address = 0;
                    gateway.Address = 0;
                    IPInterfaceProperties ipInterface = networkCard.GetIPProperties();
                    foreach (UnicastIPAddressInformation unicastAddress in ipInterface.UnicastAddresses)
                    {
                        if (unicastAddress.IPv4Mask != null && unicastAddress.IPv4Mask.Address != 0)
                            mask = unicastAddress.IPv4Mask;
                    }

                    if (mask.Address != 0)
                    {
                        foreach (GatewayIPAddressInformation gatewayAddr in networkCard.GetIPProperties().GatewayAddresses)
                        {
                            if (gatewayAddr.Address.Address != 0)
                            {
                                gateway = gatewayAddr.Address;
                                break;
                            }
                        }
                    }
                }

                if (mask.Address != 0 && gateway.Address != 0)
                    break;
            }

            if (gateway.Address == 0)
                throw (new Exception("No valid network interface detected"));

            IPAddress start = new IPAddress(gateway.Address + 0x1000000);
            long temp = mask.Address ^ 0xffffffff;
            temp += (gateway.Address & mask.Address);

            if ((temp & 0xff000000) == 0xff000000) // don't use broadcast address
                temp -= 0x1000000;

            IPAddress end = new IPAddress(temp);

            return new PingRange(start, end);
        }
    }
}
